<template>
  <div>
    <h3>多文件上传</h3>
    <div class="upload_box">
      <input
        ref="uploadInput"
        type="file"
        class="upload_input"
        @change="changeFile"
        multiple
      />
      <div class="upload_button_box">
        <button
          class="upload_button select"
          @click="chooseFile"
          :class="[{ disabled: selectButtonDisabledStyle }]"
        >
          选择文件
        </button>
        <button
          class="upload_button upload"
          @click="uploadFile"
          :class="[{ loading: uploadButtonLoadingStyle }]"
        ></button>
      </div>
      <div class="tip_box" v-if="tipBoxVisible">请选择文件</div>
      <div class="file_list_box" v-if="fileListBoxVisible" @click="removeFile">
        <table class="file_table">
          <tr>
            <td>文件名</td>
            <td>文件大小</td>
            <td>进度</td>
            <td>操作</td>
          </tr>
          <tr v-for="(file, index) in files" :key="index">
            <td>{{ file.name }}</td>
            <td>{{ parseInt((file.size / 1024 / 1024) * 100) / 100 }}MB</td>
            <td>
              <div class="upload_progress">
                <div class="value"></div>
              </div>
            </td>
            <td>
              <el-button size="small" type="text">
                <em :data-index="index">移除</em>
              </el-button>
            </td>
          </tr>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
import {uploadSingleFile} from "@/api/upload/ProgressSingleUploader.js";

export default {
  data() {
    return {
      tipBoxVisible: true,
      fileListBoxVisible: false,
      selectButtonDisabledStyle: false,
      uploadButtonLoadingStyle: false,
      files: [],
    };
  },
  methods: {
    chooseFile() {
      this.$refs.uploadInput.click();
    },
    changeFile(event) {
      let files = Array.from(event.target.files);
      if (!files.length) return;

      for (let file of files) {
        this.files.push(file);
      }

      this.setTipVisibleAndOppositeFileListVisible(false);
    },
    setTipVisibleAndOppositeFileListVisible(val) {
      this.tipBoxVisible = val;
      this.fileListBoxVisible = !val;
    },
    removeFile(event) {
      // 基于事件委托，实现移除的操作
      let target = event.target;
      if (target.tagName == "EM") {
        let index = +target.getAttribute("data-index");
        this.files.splice(index, 1);
      }
      if (!this.files.length) {
        this.setTipVisibleAndOppositeFileListVisible(true);
      }
    },
    uploadFile() {
      if (!this.files.length) {
        this.$message({
          type: "warning",
          message: "请先选择文件",
        });
        return;
      }

      // 判断文件是否满足条件
      let shouldUpload = true;
      if (this.onBeforeUpload) {
        shouldUpload = this.onBeforeUpload(file);
      }
      if (!shouldUpload) {
        this.$message({
          type: "warning",
          message: "文件不符合要求",
        });
        return;
      }

      this.setUploadInProgress(true);
      // 遍历files中的所有文件，将每个文件转换为Promise对象，
      // 并返回Promise对象的数组给promises，以便于下面Prmoise.all
      // 来判断是否所有文件都上传成功.
      let promises = this.files.map((file, index) => {
        let formData = new FormData();
        formData.append("file", file);
        return uploadSingleFile(formData, (event) => {
          let { loaded, total } = event;
          let progress = document.querySelectorAll(".value")[index];
          progress.style.width = loaded / total * 100 + "%";
        }).then(data => {
            if(data.code == 200) {
              let progress = document.querySelectorAll(".value")[index];
              progress.style.width = "100%";
              return;
            }
            if(data.code != 200) {
              return Promise.reject();
            }
        });
      });

      Promise.all(promises).then(()=> {
        this.$message({
          "type": "success",
          "message": "文件上传成功"
        })
      }).catch(() => {
        this.$message({
          "type": "error",
          "message": "有文件上传失败"
        })
      }).finally(() => {
        this.setUploadInProgress(false);
        this.setTipVisibleAndOppositeFileListVisible(true);
        this.clearFiles();
      });
    },
    setUploadInProgress(val) {
      this.selectButtonDisabledStyle = val;
      this.uploadButtonLoadingStyle = val;
    },
    clearFiles() {
      this.files.length = 0;
    }
  },
};
</script>

<style scoped>
.upload_box {
  border: #ccc dashed 1px;
  width: 400px;
  height: 150px;
  margin: auto;
}
.upload_input {
  display: none;
}
.upload_button_box {
}
.upload_button {
  margin: 5px;
  padding: 5px;
  border: #ccc outset 1px;
  border-radius: 5px;
}
.upload_button:active {
  border: #ccc solid 1px;
}
.select {
  background-color: #00b9f1;
}
.upload {
  background-color: #cce708;
}
.upload::after {
  content: "上传到服务器";
}
.tip_box,
.file_list_box {
  font-size: 12px;
}
.file_table {
  width: 100%;
}
.disabled {
  pointer-events: none;
  background-color: #ccc;
}
.loading {
  width: 23px;
  height: 23px;
  border: 5px solid #ccc;
  border-bottom-color: #ff3d00;
  border-radius: 50%;
  display: inline-block;
  background-color: #fff;
  animation: rotation 0.7s linear infinite;
  pointer-events: none;
}
.loading::after {
  content: "";
}

@keyframes rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.upload_progress {
  background-color: #ccc;
  width: 100%;
  height: 5px;
}
.upload_progress .value {
  height: 100%;
  width: 0%;
  background-color: #8ab42e;
  transition: width 0.3s;
}
</style>